package services

import (
	"io/ioutil"

	"gitee.com/RocsSun/report/config"
	"gitee.com/RocsSun/report/constants"
	"gitee.com/RocsSun/report/dates"
	"gitee.com/RocsSun/report/models"
	"gitee.com/RocsSun/report/spider/managerEngine"
	"github.com/tidwall/gjson"
	"gopkg.in/yaml.v2"
)

type YesterdayReportDataSpider struct {
	OpManager  *managerEngine.OpManagerClient
	NetFlow    *managerEngine.NetFlowSpider
	NetFlowAPI *managerEngine.NetFlowRESTClient
}

func NewYesterdayReportDataSpider() *YesterdayReportDataSpider {
	return &YesterdayReportDataSpider{
		OpManager:  managerEngine.NewOpManagerClient(),
		NetFlow:    managerEngine.NewNetFlowSpider(),
		NetFlowAPI: managerEngine.NewDefaultNetFlowRESTClient(),
	}
}

func (y *YesterdayReportDataSpider) DevOpsReportCPU(ip string) *models.Cpus {
	cps := &models.Cpus{}
	y.OpManager.Spider.Login("sunpengfei", "123456")
	resp := y.OpManager.YesterdayMonitorCpuData(ip)
	res := gjson.GetBytes(resp.Body(), "consolidatedValues.CPUUSAGE")
	if !res.Exists() {
		cps.AvgVal = -1.0
		cps.MaxVal = -1.0
		cps.MinVal = -1.0
		cps.SeriesName = "RAMUSAGE"
	} else {
		resMap := res.Map()
		if v, ok := resMap["maxVal"]; ok {
			cps.MaxVal = float32(v.Float())
		}

		if v, ok := resMap["minVal"]; ok {
			cps.MinVal = float32(v.Float())
		}
		if v, ok := resMap["seriesName"]; ok {
			cps.SeriesName = v.String()
		}
		if v, ok := resMap["avgVal"]; ok {
			cps.AvgVal = float32(v.Float())
		}
	}
	cps.IP = ip
	return cps
}

func (y *YesterdayReportDataSpider) DevOpsReportMem(ip string) *models.Mems {
	mems := &models.Mems{}

	y.OpManager.Spider.Login("sunpengfei", "123456")

	tmp := y.OpManager.DevicesMemUnit(ip)
	tmpMap := gjson.GetBytes(tmp.Body(), "ramSizeWithUnit")
	resp := y.OpManager.YesterdayMonitorMemData(ip)
	res := gjson.GetBytes(resp.Body(), "consolidatedValues.RAMUSAGE")

	if !res.Exists() {
		mems.AvgVal = -1.0
		mems.MaxVal = -1.0
		mems.MinVal = -1.0
		mems.SeriesName = "RAMUSAGE"
		// return mems
	} else {
		resMap := res.Map()
		if v, ok := resMap["maxVal"]; ok {
			mems.MaxVal = float32(v.Float())
		}

		if v, ok := resMap["minVal"]; ok {
			mems.MinVal = float32(v.Float())
		}
		if v, ok := resMap["seriesName"]; ok {
			mems.SeriesName = v.String()
		}
		if v, ok := resMap["avgVal"]; ok {
			mems.AvgVal = float32(v.Float())
		}
	}

	if tmpMap.Exists() {
		mems.RamSizeWithUnit = tmpMap.String()
	} else {
		mems.RamSizeWithUnit = "-1"
	}
	mems.IP = ip
	return mems
}

func (y *YesterdayReportDataSpider) DevOpsReportDisk(ip string) []*models.Disks {

	y.OpManager.Spider.Login("sunpengfei", "123456")
	var result []*models.Disks
	res := y.OpManager.YesterdayMonitorDiskData(ip)
	for _, v := range res {
		tmpMap := gjson.GetBytes(v.Body(), "consolidatedValues")
		if tmpMap.Exists() {
			tmpm := tmpMap.Map()
			for key := range tmpm {
				Disks := &models.Disks{}
				sss := tmpm[key].Map()
				Disks.AvgVal = float32(sss["avgVal"].Float())
				Disks.MaxVal = float32(sss["maxVal"].Float())
				Disks.MinVal = float32(sss["minVal"].Float())
				Disks.IP = ip
				Disks.CurVal = float32(sss["currVal"].Float())
				Disks.FreeVal = 100.0 - float32(sss["avgVal"].Float())
				Disks.SeriesName = sss["seriesName"].String()
				result = append(result, Disks)
			}
		} else {
			// 没有监控数据
			Disks := &models.Disks{}
			Disks.AvgVal = -1
			Disks.MaxVal = -1
			Disks.MinVal = -1
			Disks.IP = ip
			Disks.CurVal = -1
			Disks.FreeVal = -1
			Disks.SeriesName = "无数据"
			result = append(result, Disks)
		}
	}
	return result
}

func (y *YesterdayReportDataSpider) DevOpsReportService(ip string) []*models.Service {
	var result []*models.Service
	y.OpManager.Spider.Login("sunpengfei", "123456")
	resp := y.OpManager.YesterdayMonitorServicData(ip)
	// fmt.Println(resp)
	for serverName, serverResp := range resp {
		serverMap := gjson.GetBytes(serverResp.Body(), "consolidatedValues")
		data := &models.Service{}
		// 500状态码或者是没监控数据
		if !serverMap.Exists() {
			data.AvgVal = -1
			data.HisProps = "无数据"
			data.MaxVal = -1
			data.MinVal = -1
			data.PortNo = 0
			data.SeriesName = serverName
		} else {
			tmp := serverMap.Map()[serverName].Map()
			data.AvgVal = float32(tmp["avgVal"].Float())
			data.MaxVal = float32(tmp["maxVal"].Float())
			data.MinVal = float32(tmp["minVal"].Float())
			data.PortNo = 0
			data.SeriesName = serverName

			StateHistoryProps := gjson.GetBytes(serverResp.Body(), "StateHistoryProps")

			if len(StateHistoryProps.Array()) == 0 {
				data.HisProps = "无异常"
			} else {
				record := ""
				for _, value := range StateHistoryProps.Array() {
					hisDataHistoryProps := gjson.GetBytes([]byte(value.Raw), "histData")
					for _, hisData := range hisDataHistoryProps.Array() {
						start := gjson.Get(hisData.String(), "OrgStartTime").String()
						end := gjson.Get(hisData.String(), "OrgEndTime").String()
						record = start + "~" + end + "\n"
					}
				}
				data.HisProps = record
			}
		}
		data.IP = ip
		result = append(result, data)
	}
	return result
}

func (y *YesterdayReportDataSpider) DevOpsReportProcess(ip string) []*models.Process {
	var result []*models.Process
	y.OpManager.Spider.Login("sunpengfei", "123456")
	resp := y.OpManager.YesterdayMonitorProcessData(ip)
	for processName, processResp := range resp {
		// fmt.Println(processResp)
		processMap := gjson.GetBytes(processResp.Body(), "perfProp.legendProps")
		// fmt.Println(processMap)
		data := &models.Process{}
		// 500状态码或者是没监控数据
		if !processMap.Exists() {
			data.AbsMemAvgVal = "-1"
			data.AbsMemMaxVal = "-1"
			data.AbsMemMinVal = "-1"
			data.CpuAvgVal = -1
			data.CpuMaxVal = -1
			data.CpuMinVal = -1
			data.MemAvgVal = -1
			data.MemMaxVal = -1
			data.MemMinVal = -1
			data.StatusText = "未知"
			data.SeriesName = processName
		} else {
			tmp := processMap.Map()
			data.AbsMemAvgVal = tmp["absMemAvgVal"].String()
			data.AbsMemMaxVal = tmp["absMemMaxVal"].String()
			data.AbsMemMinVal = tmp["absMemMinVal"].String()
			data.CpuAvgVal = float32(tmp["CPUAvgVal"].Float())
			data.CpuMaxVal = float32(tmp["CPUMaxVal"].Float())
			data.CpuMinVal = float32(tmp["CPUMinVal"].Float())
			data.MemAvgVal = float32(tmp["MemAvgVal"].Float())
			data.MemMaxVal = float32(tmp["MemMaxVal"].Float())
			data.MemMinVal = float32(tmp["MemMixVal"].Float())
			switch tmp["MemMixVal"].Int() {
			case 1:
				data.StatusText = "Error"
			case 2:
				data.StatusText = "Turbble"
			case 3:
				data.StatusText = "Warning"
			case 4:
				data.StatusText = "Down"
			case 5:
				data.StatusText = "Normal"
			case 6:
				data.StatusText = "Info"
			}
			data.SeriesName = processName

		}
		data.IP = ip
		result = append(result, data)
	}
	return result
}

func (y *YesterdayReportDataSpider) DevOpsReportNetWork() []*models.NetFlowData {
	var result []*models.NetFlowData
	y.UpdateNetFlowConfig()
	for _, v := range config.ReadNetFlowList() {
		for _, value := range v {
			// var data *models.NetFlowData = &models.NetFlowData{}
			var data *models.NetFlowData = new(models.NetFlowData)
			resp := y.NetFlowAPI.ConvData(value.InterfaceID)
			json := gjson.ParseBytes(resp.Body())

			data.CreatedAt = dates.Nows
			data.CheckedDate = dates.Nows

			if json.Get("error").Exists() {
				data.App = "-1"
				data.DstIP = value.NATIP
				data.DstPort = "-1"
				data.SourceIp = value.TradeIP
				data.SourcePort = "-1"
				data.Protocol = "-1"
				data.Traffic = "-1"
				data.SysName = value.InnerIP
				data.DisplayName = value.DisplayName
				result = append(result, data)
			} else {
				for _, item := range json.Get("Data").Array() {
					if item.Get("dst").String() == value.NATIP && item.Get("src").String() == value.TradeIP {
						data.App = item.Get("app").String()
						data.DstIP = value.NATIP
						data.DisplayName = value.DisplayName
						data.DstPort = item.Get("dstport").String()
						data.SourceIp = value.TradeIP
						data.SourcePort = item.Get("port").String()
						data.Protocol = item.Get("prot").String()
						data.Traffic = item.Get("traffic").String()
						data.SysName = value.InnerIP
						result = append(result, data)
					}
				}
			}
		}
	}
	return result
}

func (y *YesterdayReportDataSpider) UpdateNetFlowConfig() {
	resp := y.NetFlowAPI.ListDevices()
	respList := gjson.ParseBytes(resp.Body())
	netFlowList := config.ReadNetFlowList()
	for _, v := range netFlowList {
		for _, value := range v {
			if !(value.RouterID != "" && value.RouterIP != "") {
				for _, item := range respList.Array() {
					if item.Get("Name").String() == value.RouterName {
						value.RouterID = item.Get("routerID").String()
						value.RouterIP = item.Get("routerIP").String()
					}
				}
			}
			if value.InterfaceID == "" {
				resps := y.NetFlowAPI.DailyIndexInterfaceData(value.RouterID)
				respsJson := gjson.ParseBytes(resps.Body())
				for _, items := range respsJson.Get("data").Array() {
					if items.Get("Name").String() == value.InterfaceName {
						value.InterfaceID = items.Get("ID").String()
					}
				}
			}
		}
	}
	res, _ := yaml.Marshal(netFlowList)
	ioutil.WriteFile(constants.NetFlowRestAPIConfigPath, res, 0664)
}
